package cn.test.futrue.CompletableFuture.CompletableFuture3;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class PriceDemoScene1 {
    private static List<Shop> shops = new ArrayList<>();
    static {
        for (int i = 1; i < 9; i++) {
            shops.add(new Shop("shop" + i));
        }
    }
    public static void main(String[] args) {
        PriceDemoScene1 priceDemoScene1 = new PriceDemoScene1();
        Long start = System.currentTimeMillis();
        System.out.println(priceDemoScene1.findPrices3_CompletableFuture_1("haha"));
        System.out.println("服务耗时：" + (System.currentTimeMillis() - start));
    }

    public List<String> findPrices(String product) {

        Executor executor = Executors.newFixedThreadPool(40);
        List<CompletableFuture<String>> futureList = shops.stream().map(new Function<Shop, CompletableFuture<String>>() {
            @Override
            public CompletableFuture<String> apply(Shop shop) {

                return CompletableFuture.supplyAsync(new Supplier<String>() {
                    @Override
                    public String get() {
                        return String.format("%s price is %.2f ", shop.getName(), shop.getPrice(product).getPrice());
                    }
                }, executor);
            }
        }).collect(Collectors.toList());
        return futureList.stream().map(new Function<CompletableFuture<String>, String>() {
            @Override
            public String apply(CompletableFuture<String> future) {
                return future.join();
            }
        }).collect(Collectors.toList());
    }

    /**方法1：串行     8条线程，所以是8秒
     * [shop1 price is 14.51 , shop2 price is 25.01 , shop3 price is 2.11 , shop4 price is 25.10 , shop5 price is 77.47 , shop6 price is 61.09 , shop7 price is 40.40 , shop8 price is 10.68 ]
     * 服务耗时：8142
     */
    public List<String> findPrices1_stream(String product){
        return shops.stream()
                .map(shop -> String.format("%s price is %.2f ", shop.getName(), shop.getPrice(product).getPrice()))
                .collect(Collectors.toList());
    }
    /**方法2： 并行： .parallel()      并行流输出结果(4核电脑)：4核跑4条线程，所以是2秒
     * [shop1 price is 48.90 , shop2 price is 82.99 , shop3 price is 43.06 , shop4 price is 52.75 , shop5 price is 5.22 , shop6 price is 22.97 , shop7 price is 10.45 , shop8 price is 36.63 ]
     * 服务耗时：2094
     */
    public List<String> findPrices2_parallelStream(String product){
                return shops.parallelStream()
                        .map(shop -> String.format("%s price is %.2f ", shop.getName(), shop.getPrice(product).getPrice()))
                        .collect(Collectors.toList());
    }
    /**方法3：CompletableFuture 初试         结果是3秒，有点失望，因为写了一大串东西，还不如并行流好用
     * [shop1 price is 60.89 , shop2 price is 52.46 , shop3 price is 74.61 , shop4 price is 0.70 , shop5 price is 75.17 , shop6 price is 94.40 , shop7 price is 5.99 , shop8 price is 90.28 ]
     * 服务耗时：3125
     */
    public List<String> findPrices3_CompletableFuture_1(String product){
        List<CompletableFuture<String>> priceFuture =
            shops.stream()
                    .map(shop -> CompletableFuture.supplyAsync(
                                    () -> String.format("%s price is %.2f ", shop.getName(), shop.getPrice(product).getPrice())
                                )
                    )
            .collect(Collectors.toList());
        //此处的  stream()/parallelStream() 效果都是3秒
        return priceFuture.stream().map(CompletableFuture::join).collect(Collectors.toList());
    }
    /**方法4：completablefuture + 线程池         当调用查询服务加到9个的时候，并行流和completablefuture都是三秒，
     * 因为completablefuture默认的启动机制是和并行流一样的，但是completablefuture这个方法可以通过配置，创建一个线程池。
     * [shop1 price is 43.53 , shop2 price is 47.49 , shop3 price is 68.18 , shop4 price is 53.55 , shop5 price is 79.60 , shop6 price is 20.05 , shop7 price is 6.16 , shop8 price is 33.47 ]
     * 服务耗时：1096
     *这里查询任务给它开到了17个，1秒就搞定了！并行流则就要5秒
     *在这里，可以学习下别人的 newfixedthreadpool 配置线程数，当然，不精确的话 用这个newcachedthreadpool就完事了
     * t = n * u *(1 + w/c)
     * n是cpu核数，u是cpu占用比
     * 最佳线程数目 = （线程等待时间与线程cpu时间之比 + 1）* cpu数目
     */
    public List<String> findPrices4_CompletableFuture_Executors(String product){
        Executor executor = Executors.newCachedThreadPool();
        //Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(),100));
        List<CompletableFuture<String>> priceFuture =
            shops.stream()
                .map(
                        shop -> CompletableFuture.supplyAsync(
                            () -> String.format("%s price is %.2f ", shop.getName(), shop.getPrice(product).getPrice()), //shop.getPice(product)
                            executor
                        )
                )
                .collect(Collectors.toList());
        return priceFuture.stream().map(CompletableFuture::join).collect(Collectors.toList());
    }


}
